package com.wolf.antlr;

import com.wolf.antlr.cpp.CPP14Lexer;
import com.wolf.antlr.cpp.CPP14Parser;
import com.wolf.antlr.cpp.CPP14ParserBaseListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CppSearcher {
    public static String file;

    static List<MethodFragment> searchFunctions(String fileName, CppListenerImp listener) {
        Lexer lexer;
        try {
            lexer = new CPP14Lexer(CharStreams.fromFileName(fileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        TokenStream tokenStream = new CommonTokenStream(lexer);
        file = fileName;
        CPP14Parser parser = new CPP14Parser(tokenStream);
        ParseTree tree = parser.translationUnit();
        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(listener, tree);
        return listener.getMethodFragments();
    }

    // 定义一个readLine方法，用于读取给定文本文件的指定行数
    public static String readLine(String filename, int lineNumber, String regx) {

        File file = new File(filename);
        // 定义一个空字符串用于存储结果
        String result = "";
        // 定义一个计数器用于记录当前行数
        int count = 0;
        // 使用try-with-resources语句创建BufferedReader对象，自动关闭资源
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            // 定义一个临时字符串用于存储每一行的内容
            String temp;
            // 使用while循环遍历文件内容
            while ((temp = br.readLine()) != null) {
                // 每读取一行，计数器加一
                count++;
                // 如果当前行数等于要读取的行数
                if (count == lineNumber) {
                    // 将该行内容赋值给结果字符串
                    Pattern p = Pattern.compile(regx);
                    Matcher m = p.matcher(temp);
                    if (m.find()) {
                        result = m.group();
                    }
                    // 跳出循环
                    break;
                }
            }
        } catch (IOException e) {
            // 捕获异常并打印
            e.printStackTrace();
        }
        // 返回结果字符串
        return result;
    }

    public static void main(String[] args) {
        CppListenerImp listener = new CppListenerImp();
        String fileName = Main.parserArgs(args, listener);
        List<MethodFragment> methodFragments = searchFunctions(fileName, listener);
        methodFragments.forEach(methodFragment -> System.out.printf("%s, %s, %s, %s, %s\n",
                methodFragment.startIndex(),
                methodFragment.endIndex(),
                methodFragment.startLine(),
                methodFragment.endLine(),
                methodFragment.methodDeclaration()));
    }


    static class CppListenerImp extends CPP14ParserBaseListener implements IListener {


        private String getMethodDeclaration(CPP14Parser.FunctionDefinitionContext ctx) {
            CPP14Parser.DeclSpecifierSeqContext declSpecifierSeqContext = ctx.declSpecifierSeq();
            CPP14Parser.DeclaratorContext declaratorContext = ctx.declarator();
            String regx;
            if (ctx.virtualSpecifierSeq() == null)
                regx = declSpecifierSeqContext.start.getText() + ".*\\" + declaratorContext.stop.getText();
            else
                regx = declSpecifierSeqContext.start.getText() + ".*" + ctx.virtualSpecifierSeq().getText();
            return readLine(file, declSpecifierSeqContext.start.getLine(), regx);
        }

        @Override
        public void enterFunctionDefinition(CPP14Parser.FunctionDefinitionContext ctx) {
            super.enterFunctionDefinition(ctx);
            String declaration = this.getMethodDeclaration(ctx);
            this.search(ctx, declaration);
        }
    }
}
